/*
 * Copyright (c) 2014 pkzd/1.0, 颜文泽(robin)
 * All rights reserved.
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *     1 Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     2 Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include	<stdio.h>
#include	<string.h>
#include	<syscall.h>

char *cmdlist[] = {
	"cd", "ls", "cat", "date", NULL
};

void	do_cmd(char *cmd);
char 	*skip_space(char *p);

int
main(int argc, char *argv[])
{
	int i, c;
	char buf[80];

	i = 0;
	printf("pkzd#");
	for( ; ; ){
		c = getchar();
		if(c == '\n'){
			buf[i] = '\0';
			do_cmd(buf);
			i = 0;
			printf("pkzd#");
		}else if(c == EOF){
			i = 0;
			printf("pkzd#");
		}else
			buf[i++] = c;
	}
}

char *
skip_space(char *p)
{
	char *s;
	
	s = p;
	while(*p && (*p == ' ' || *p == '\t'))
		p++;
	if(s != p)
		*s = '\0';
	return *p ? p : NULL;
}

void
do_cmd(char *cmd)
{
	char *p;
	int i, pid;
	char buf[80];
	char *argv[NARGV];

	i = 0;
	for(p = cmd; p && *p && (p = skip_space(p)); ){
		argv[i++] = p;
		if(i >= (NARGV - 2))
			break;
		while(*p && *p != ' ' && *p != '\t')
			p++;
	}
	argv[i] = NULL;
	for(i = 0; cmdlist[i]; i++){
		if(argv[0] && strcmp(argv[0], cmdlist[i]) == 0){
			if(strcmp(argv[0], "cd") == 0){
				if(!argv[1]){
					printf("Usage: cd directory\n");
					return;
				}
				if(chdir(argv[1]) == -1)
					printf("Error: cd to directory %s fault\n", argv[1]);
				return;
			}
			memmove(buf, "/bin/", 5);
			memmove(buf + 5, argv[0], strlen(argv[0]) + 1);
			argv[0] = buf;
			switch(pid = fork()){
			case -1:
				printf("Error: fork fault\n");
				return;
			case 0:
				if(execve(argv[0], argv, NULL) == -1)
					printf("Error: execve %s fault\n", argv[0]);
				exit(1);
			default:
				while((i = wait(NULL)) != pid && i != -1)
					;
				return;
			}
		}
	}
	printf("Error: unknown command %s\n", argv[0]);	
}
